package me.zhengjie.modules.quartz.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qiaofang.applet.service.other.domain.CityCompany;
import com.qiaofang.applet.service.other.domain.Corporation;
import com.qiaofang.applet.service.other.service.CorporationService;
import com.qiaofang.applet.service.property.domain.Property;
import com.qiaofang.applet.service.property.service.PropertyService;
import com.qiaofang.core.gatewayclient.GatewayTemplate;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.quartz.service.constants.SyncConstants;
import me.zhengjie.modules.quartz.task.dto.EstateRockBindDTO;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static me.zhengjie.modules.quartz.service.constants.SyncConstants.ON;

@Slf4j
@Component
public class V20EstateRockIdBrushTask {

    @Autowired
    private CorporationService corporationService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private GatewayTemplate gatewayTemplate;


    public void run() {
        log.info("V20EstateRockIdBrushTask run start");
        Corporation corporation = new Corporation();
        corporation.setDeleted(Boolean.FALSE);
        corporation.setV20Flag(Boolean.TRUE);
        Iterable<Corporation> list = corporationService.findAll(Example.of(corporation));
        list.forEach(item -> {
            String corporationCode = item.getCorporationCode();
            Criteria criteria = Criteria.where("corporationCode").is(corporationCode).and("status").is(1);
            List<CityCompany> companies = mongoTemplate.find(new Query(criteria), CityCompany.class);
            companies.forEach(company -> {
                processByCompany(company.getCompanyUuid());
            });
        });
        log.info("V20EstateRockIdBrushTask run end");
    }

    private void processByCompany(String companyUuid) {
        Aggregation aggregationSale = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("companyUuid").is(companyUuid)
                        .and("tradeStatus").is("有效").and("square").ne(null).and("estateUuid").ne(null)),
                Aggregation.group("estateUuid")
                        .first("estateUuid").as("estateUuid"));
        AggregationResults<EstateRockBindDTO> results = mongoTemplate.aggregate(aggregationSale, "property_property", EstateRockBindDTO.class);
        List<EstateRockBindDTO> estateDTOS = results.getMappedResults();
        List<String> uuidList = estateDTOS.stream().map(EstateRockBindDTO::getEstateUuid).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(uuidList)){
            return;
        }
        List<EstateRockBindDTO> rockBindList = Lists.newArrayList();
        List<List<String>> lists = Lists.partition(uuidList, 200);
        lists.forEach(list -> {
            JSONArray jsonArray = doRequest(companyUuid, new HashSet<>(list));
            if (!CollectionUtils.isEmpty(jsonArray)){
                rockBindList.addAll(jsonArray.toJavaList(EstateRockBindDTO.class));
            }
        });
        if (CollectionUtils.isEmpty(rockBindList)){
            return;
        }
        List<String> nullRockList = Lists.newArrayList();
        Map<String, Long> estateRockMap = Maps.newHashMap();
        rockBindList.forEach(item-> {
            if (item.isDeleted() || Objects.isNull(item.getEstateRockId())){
                nullRockList.add(item.getEstateUuid());
            }else {
                estateRockMap.put(item.getEstateUuid(), item.getEstateRockId());
            }
        });
        if (!CollectionUtils.isEmpty(nullRockList)){
            Update update = new Update();
            update.set("estateRockId", null);
            mongoTemplate.updateMulti(new Query(Criteria.where("companyUuid").is(companyUuid)
                    .and("estateUuid").in(nullRockList)), update, Property.class);
            log.info("公司：{} 下的磐石楼盘id应该置空，楼盘uuid列表：{}", companyUuid, nullRockList);
        }
        if (!CollectionUtils.isEmpty(estateRockMap)){
            Set<String> set = estateRockMap.keySet();
            List<Property> propertyList = mongoTemplate.find(new Query(
                    Criteria.where("companyUuid").is(companyUuid)
                            .and("tradeStatus").is("有效")
                            .and("square").ne(null)
                            .and("estateUuid").in(set)),
                    Property.class);
            propertyList.forEach(item -> {
                item.setEstateRockId(estateRockMap.get(item.getEstateUuid()));
                log.info("公司：{} 下的房源：{} 被设置磐石id：{}", companyUuid, item.getPropertyNo(), item.getEstateRockId());
            });
            propertyService.saveAll(propertyList);
        }
    }

    /**
     * 查询业务数据
     * @param companyUuid
     * @param uuidSet
     * @return
     */
    private JSONArray doRequest(String companyUuid, Set<String> uuidSet) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("companyUuid", companyUuid);

        log.info("sync params {},header {}", uuidSet, headers);
        JSONObject param = new JSONObject();
        param.put("uuidSet", uuidSet);
        JSONObject result;
        try {
            result = gatewayTemplate.postForObject(SyncConstants.V20_ESTATE_ROCK_API, param, headers, JSONObject.class);
            log.info("sync result {}", result);
            String responseCode = result.getString("responseCode");
            if(!StringUtils.equals(ON, responseCode)) {
                return null;
            }
            return result.getJSONArray("data");
        } catch (Exception e) {
            log.error("sync error", e);
            return null;
        }
    }
}
